package com.coder.service;

import java.sql.Time;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;

import com.coder.dao.IsaDao;
import com.coder.model.DayIsa;
import com.coder.model.Isa;
import com.coder.model.IsaAvg;
import com.coder.model.MonthIsa;
import com.coder.model.WaveThreshold;
import com.coder.utils.CommUtil;
import com.coder.utils.DateUtilMy;
import com.coder.utils.DecodeUtil;

public class IsaService {
	
	private IsaDao isaDao = null;
	private WaveService waveService = null;
	private int wavesNum = 256;
	

	public List<MonthIsa> getMonthIsaByMonth(String month) {
		List<MonthIsa> res = null;
		try{
			res = isaDao.getMonthIsaByMonth(month);
		}catch(Exception e){
			e.printStackTrace();
		}
		if(res==null){
			return null;
		}
		
		for(int i=0;i<res.size();i++){
			MonthIsa monthIsa = res.get(i);
			monthIsa.setAvgValues(DecodeUtil.str2floats(monthIsa.getAvgValStr()));
			monthIsa.setMaxValues(DecodeUtil.str2floats(monthIsa.getMaxValStr()));
			monthIsa.setMinValues(DecodeUtil.str2floats(monthIsa.getMinValStr()));
		}
		return res;
	}
	
	/**根据一天的日期获取这一天的isa的平均值，封装在DayIsa中，包括这一天的平均值，最大值，最小值
	 *@return 返回值是list的原因是有mode0 mode1两种模式
	 * */
	public List<DayIsa> getDayIsaByDay(Date day){
		
		List<DayIsa> res = null;
		try{
			res = isaDao.getDayIsaByDay(day);
		}catch(Exception e){
			e.printStackTrace();
		}
		if(res==null){
			return null;
		}
		
		for(int i=0;i<res.size();i++){
			DayIsa dayIsa = res.get(i);
			dayIsa.setAvgValues(DecodeUtil.str2floats(dayIsa.getAvgValStr()));
			dayIsa.setMaxValues(DecodeUtil.str2floats(dayIsa.getMaxValStr()));
			dayIsa.setMinValues(DecodeUtil.str2floats(dayIsa.getMinValStr()));
			dayIsa.setDayStr(DateUtilMy.dayFormat.format(dayIsa.getDay()));
		}
		return res;
	}
	
	/**
	 * 通过DayIsa来计算MonthIsa
	 * @param 月份,字符串类型
	 * @return 返回的第一个MonthIsa表示模式为0的数据，第二个是模式为1的数据
	 */
	public MonthIsa[] saveAvgIsaOfaMonth(String month){
		
		List<DayIsa> dayIsas = getDayIsaByMonth(month);
		
		if(dayIsas==null){
			return null;
		}
		String yearStr = month.split("-")[0];	//获取四位数年份，格式为yyyy 
		
		System.out.println(yearStr);
		
		MonthIsa monthIsa0 = new MonthIsa();
		monthIsa0.setMonthStr(month);
		monthIsa0.setYearStr(yearStr);
		monthIsa0.setMode(0);
		float[]	avgVal0 = new float[wavesNum];
		float[]	minVal0 = CommUtil.getaMinArray(wavesNum);
		float[]	maxVal0 = CommUtil.getaMaxArray(wavesNum);
		float curCount0 = 0;
		
		MonthIsa monthIsa1 = new MonthIsa();
		monthIsa1.setMonthStr(month);
		monthIsa1.setYearStr(yearStr);
		monthIsa1.setMode(1);
		float[]	avgVal1 = new float[wavesNum];
		float[]	minVal1 = CommUtil.getaMinArray(wavesNum);
		float[]	maxVal1 = CommUtil.getaMaxArray(wavesNum);
		float curCount1 = 0;
		
		for(int i=0;i<dayIsas.size();i++){
			float[] datas = dayIsas.get(i).getAvgValues();
			float recordNum = dayIsas.get(i).getRecordNum();
			
			if(dayIsas.get(i).getMode()==0){
				for(int j=0;j<wavesNum;j++){
					avgVal0[j] = avgVal0[j]*(curCount0/(curCount0+recordNum))
							    +datas[j]*(recordNum/(curCount0+recordNum));
				}
				curCount0 += recordNum;
			}else{
				for(int j=0;j<wavesNum;j++){
					avgVal1[j] = avgVal1[j]*(curCount1/(curCount1+recordNum))
							    +datas[j]*(recordNum/(curCount1+recordNum));
				}
				curCount1 += recordNum;
			}
		}
		
		monthIsa0.setRecordNum(curCount0);
		monthIsa0.setAvgValStr(DecodeUtil.floats2Str(avgVal0));
		monthIsa0.setMaxValStr(DecodeUtil.floats2Str(maxVal0));
		monthIsa0.setMinValStr(DecodeUtil.floats2Str(minVal0));
		
		monthIsa1.setRecordNum(curCount1);
		monthIsa1.setAvgValStr(DecodeUtil.floats2Str(avgVal1));
		monthIsa1.setMaxValStr(DecodeUtil.floats2Str(maxVal1));
		monthIsa1.setMinValStr(DecodeUtil.floats2Str(minVal1));
		
		isaDao.saveMonthIsa(monthIsa0);
		isaDao.saveMonthIsa(monthIsa1);
		
		MonthIsa[] monthIsa01 = new MonthIsa[2];
		monthIsa01[0] = monthIsa0;
		monthIsa01[1] = monthIsa1;
		return monthIsa01;
	}
	
	
	/**
	 * 获取某一天的isa数据的平均值，最大值 以及最小值
	 * @param date 表示某一天，不需要指出具体小时分钟
	 * @return 返回的第一个DayIsa表示模式为0的数据，第二个是模式为1的数据
	 */
	public DayIsa[] saveAvgIsaOfaDay(Date day){
		
		List<Isa> isas = getIsaByDay(day);
		
		if(isas==null){
			return null;
		}
		String monthStr = DateUtilMy.monthFormat.format(day); 
		
		DayIsa dayIsa0 = new DayIsa();
		dayIsa0.setDay(day);
		dayIsa0.setMode(0);
		dayIsa0.setMonthStr(monthStr);
		float[]	avgVal0 = new float[wavesNum];
		float[]	minVal0 = CommUtil.getaMinArray(wavesNum);
		float[]	maxVal0 = CommUtil.getaMaxArray(wavesNum);
		int count0 = 0;
		
		//TODO 暂时没有求每个月的最大值与最小值
		DayIsa dayIsa1 = new DayIsa();
		dayIsa1.setDay(day);
		dayIsa1.setMode(1);
		dayIsa1.setMonthStr(monthStr);
		float[]	avgVal1 = new float[wavesNum];
		float[]	minVal1 = CommUtil.getaMinArray(wavesNum);
		float[]	maxVal1 = CommUtil.getaMaxArray(wavesNum);
		int count1 = 0;
		
		for(int i=0;i<isas.size();i++){
			
			ArrayList<Float> datas = isas.get(i).getFloatDatas();
			
			if(isas.get(i).getMode()==0){
				for(int j=0;j<wavesNum;j++){
					avgVal0[j] += datas.get(j);
					if(datas.get(j)>maxVal0[j]){
						maxVal0[j] = datas.get(j);
					}
					if(datas.get(j)<minVal0[j]){
						minVal0[j] = datas.get(j);
					}
				}
				count0++;
			}else{
				for(int j=0;j<wavesNum;j++){
					avgVal1[j] += datas.get(j);
					if(datas.get(j)>maxVal1[j]){
						maxVal1[j] = datas.get(j);
					}
					if(datas.get(j)<minVal1[j]){
						minVal1[j] = datas.get(j);
					}
				}
				count1++;
			}
		}
		
		for(int i=0;i<wavesNum;i++){
			avgVal0[i] /= count0;
			avgVal1[i] /= count1;
		}
		
		dayIsa0.setRecordNum(count0);
		dayIsa0.setAvgValStr(DecodeUtil.floats2Str(avgVal0));
		dayIsa0.setMaxValStr(DecodeUtil.floats2Str(maxVal0));
		dayIsa0.setMinValStr(DecodeUtil.floats2Str(minVal0));
		
		dayIsa1.setRecordNum(count1);
		dayIsa1.setAvgValStr(DecodeUtil.floats2Str(avgVal1));
		dayIsa1.setMaxValStr(DecodeUtil.floats2Str(maxVal1));
		dayIsa1.setMinValStr(DecodeUtil.floats2Str(minVal1));
		
		isaDao.saveDayIsa(dayIsa0);
		isaDao.saveDayIsa(dayIsa1);
		
		DayIsa[] dayIsa01 = new DayIsa[2];
		dayIsa01[0] = dayIsa0;
		dayIsa01[1] = dayIsa1;
		return dayIsa01;
	}

	/**
	 * 返回一个月的平均DayIsa数据
	 * @param month 月份
	 * @return 模式分别为0和1的DayIsa数据
	 */
	public List<DayIsa> getDayIsaByMonth(String month){
		
		List<DayIsa> dayIsas = null;
		try{
			dayIsas = isaDao.getDayIsaByMonth(month);
		}catch(Exception e){
			e.printStackTrace();
		}
		
		if(dayIsas==null){
			return null;
		}
		
		//将数据库中的字符串格式的数据转换为浮点数格式的数据
		for(int i=0;i<dayIsas.size();i++){
			dayIsas.get(i).setAvgValues(DecodeUtil.str2floats(dayIsas.get(i).getAvgValStr()));
			dayIsas.get(i).setMaxValues(DecodeUtil.str2floats(dayIsas.get(i).getMaxValStr()));
			dayIsas.get(i).setMinValues(DecodeUtil.str2floats(dayIsas.get(i).getMinValStr()));
		}
		
		return dayIsas;
	}
	
	/**
	 * 根据某一天获取Isa数据，此方法的主要目的在将isa的二进制数据解码
	 * @param day
	 * @return
	 */
	public List<Isa> getIsaByDay(Date day){
		List<Isa> isas = isaDao.getIsaByDay(day);
		
		if(isas==null){
			return null;
		}
		byte[] byteTemp = new byte[4];
		for(int i=0;i<isas.size();i++){
			
			String date = DateUtilMy.dayFormat.format(isas.get(i).getCDate());
			String time = isas.get(i).getCTime().toString();
			String dateTimeString = date+" "+time;
			isas.get(i).setDateTime(dateTimeString);
			
			long longDate = 0;
			try {
				longDate = DateUtilMy.secondFormat.parse(dateTimeString).getTime();
			} catch (ParseException e) {
				e.printStackTrace();
			}
			isas.get(i).setLongTime(longDate);		 
			
			if(isas.get(i).getMode()==0)
				isas.get(i).setFloatDatas(bytes2floats40(isas.get(i).getData(),byteTemp));
			else
				isas.get(i).setFloatDatas(bytes2floats41(isas.get(i).getData()));
		}
		return isas;
	}
	
	/**
	 * 
	 * @param dateBefore 字符串格式：yyyy-MM-dd 开始的日期
	 * @param timeBefore 字符串格式：hh:mm:ss 开始时间
	 * @param dateAfter		结束日期
	 * @param timeAfter	            结束时间
	 * @param interval		每隔interval时间计算一个平均值，以分钟为单位
	 * @param waveAlerm	用来接收超过阈值的波长，以报警
	 * @return	返回一个interval时间段内，各个波长吸光度的平均值
	 */
	public List<IsaAvg> getAverageData(String dateBefore,String timeBefore,
			String dateAfter,String timeAfter,int interval,TreeMap<String,List<String>> waveAlerm){
		
		List<Isa> isas = getIsaData(dateBefore, timeBefore, dateAfter, timeAfter);

		if(isas==null){
			return null;
		}
		//获取各个波长的阈值
		List<WaveThreshold> waves = waveService.getAllWaveThreshold();
		
		List<IsaAvg> res = new ArrayList<IsaAvg>();
		for(int i=0;i<isas.size();){ 	//i增1操作在while循环中实现
			long start = isas.get(i).getLongTime();
			long end = start+interval*60*1000;
			String startDateTime = isas.get(i).getDateTime();
			
			
			IsaAvg isaAvgMode0 = new IsaAvg();
			isaAvgMode0.setInterval(interval);
			isaAvgMode0.setProdNr(isas.get(i).getProdNr());
			isaAvgMode0.setSensorNr(isas.get(i).getSensorNr());
			isaAvgMode0.setSerNr(isas.get(i).getSerNr());
			isaAvgMode0.setMode(0);
			isaAvgMode0.setStartDateTime(isas.get(i).getDateTime()); //格式yyyy-MM-DD hh:mm:ss
			
			IsaAvg isaAvgMode1 = new IsaAvg();
			isaAvgMode1.setInterval(interval);
			isaAvgMode1.setProdNr(isas.get(i).getProdNr());
			isaAvgMode1.setSensorNr(isas.get(i).getSensorNr());
			isaAvgMode1.setSerNr(isas.get(i).getSerNr());
			isaAvgMode1.setMode(1);
			isaAvgMode1.setStartDateTime(isas.get(i).getDateTime());
			
			float[] mode0datas = new float[wavesNum];
			float[] mode1datas = new float[wavesNum];
			
			int count1 = 0,count0 = 0;
			while(i<isas.size() && isas.get(i).getLongTime()<end){	//while是累加过程
				
				if(isas.get(i).getMode()==1){
					for(int j=0;j<wavesNum;j++){
						mode1datas[j] += isas.get(i).getFloatDatas().get(j);
					}
					count1++;
				}else{
					for(int j=0;j<wavesNum;j++){
						mode0datas[j] += isas.get(i).getFloatDatas().get(j);
					}
					count0++;
				}
				i++;
			}
			
			for(int j=0;j<wavesNum;j++){	//求平均值过程，现在仅考虑mode 0
				mode1datas[j] /= count1;
				mode0datas[j] /= count0;
					
				//TODO 超过阈值，放入最后一个参数中,本记录日期格式：yyyy-MM-DD hh:mm:ss
				float threshold = waves.get(j).getThreshold();
				int wave = waves.get(j).getWaveVal();
				if(threshold !=0 && mode0datas[j] >= threshold){
					String[] dateTime = startDateTime.split(" ");
					if(waveAlerm.containsKey(dateTime[0])){
						waveAlerm.get(dateTime[0]).add(wave+"-"+dateTime[1]+"-"+mode0datas[j]+"\n");
					}else{
						ArrayList<String> alerm = new ArrayList<String>();
						alerm.add(wave+"-"+dateTime[1]+"-"+mode0datas[j]+"\n");
						waveAlerm.put(dateTime[0], alerm);
					}
				}
			}
			
			isaAvgMode0.setAvgDatas(mode0datas);
			isaAvgMode1.setAvgDatas(mode1datas);
			res.add(isaAvgMode0);
			res.add(isaAvgMode1);
			
		}
		
		return res;
	}
	
	/**
	 * 获取一个时间段内的isa数据，参数为时间段
	 * @param dateBefore 字符串格式：yyyy-MM-dd
	 * @param timeBefore 字符串格式：hh:mm:ss
	 * @param dateAfter
	 * @param timeAfter
	 * @return 返回Isa数据，其中各个波长的吸光度为float类型
	 */
	public List<Isa> getIsaData(String dateBefore,String timeBefore,String dateAfter,String timeAfter){
	
		Date dBefore = null;
		Time tBefore = null;
		Date dAfter = null;
		Time tAfter = null;
		try {
			dBefore = DateUtilMy.dayFormat.parse(dateBefore);
			tBefore = Time.valueOf(timeBefore);
			dAfter = DateUtilMy.dayFormat.parse(dateAfter);
			tAfter = Time.valueOf(timeAfter);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		List<Isa>  isas = null;
		
		try{
			isas = isaDao.getDataBetweenDate(dBefore,tBefore,dAfter,tAfter);
		}catch(Exception e){
			e.printStackTrace();
		}
		
		if(isas==null){
			return null;
		}
		
		//将所有字节数组转化为float数据,前几行为临时变量
		byte[] byteTemp = new byte[4];
		for(int i=0;i<isas.size();i++){
			
			//处理时间,格式为：yyyy-MM-dd hh:mm:ss
			String date = DateUtilMy.dayFormat.format(isas.get(i).getCDate());
			String time = isas.get(i).getCTime().toString();
			String dateTimeString = date+" "+time;
			isas.get(i).setDateTime(dateTimeString);
			
			long longDate = 0;
			try {
				longDate = DateUtilMy.secondFormat.parse(dateTimeString).getTime();
			} catch (ParseException e) {
				e.printStackTrace();
			}
			isas.get(i).setLongTime(longDate);		 
			
			//处理数据
			if(isas.get(i).getMode()==0){
				isas.get(i).setFloatDatas(bytes2floats40(isas.get(i).getData(),byteTemp));
			}
			else{
				isas.get(i).setFloatDatas(bytes2floats41(isas.get(i).getData()));
			}
		}
		
		return isas;
	}
	
	//模式为0的数据的解码
	private ArrayList<Float> bytes2floats40(byte[] bytes,byte[] byteTemp){
		ArrayList<Float> temp = new ArrayList<Float>();
		for(int i=0;i+3<bytes.length;i+=4){
			byteTemp = Arrays.copyOfRange(bytes, i, i+4);
			temp.add(DecodeUtil.fromBytes2float(byteTemp));
		}
		return temp;
	}
	
	//模式为1的数据的解码
	private ArrayList<Float> bytes2floats41(byte[] bytes){
		ArrayList<Float> temp = new ArrayList<Float>();
		byte[] byteTemp = new byte[2];
		for(int i=0;i+1<bytes.length;i+=2){
			byteTemp = Arrays.copyOfRange(bytes, i, i+2);
			temp.add((float) getInt(byteTemp));
		}
		return temp;
	}
	
	private int getInt(byte[] bytes) {
		return (0xff & bytes[0]) | (0xff00 & (bytes[1] << 8));
	}
	
	public IsaDao getIsaDao() {
		return isaDao;
	}

	public void setIsaDao(IsaDao isaDao) {
		this.isaDao = isaDao;
	}

	public WaveService getWaveService() {
		return waveService;
	}

	public void setWaveService(WaveService waveService) {
		this.waveService = waveService;
	}

}
